package net.javastone.toolkit.comparer.yml;


import com.fasterxml.jackson.databind.JsonNode;
import net.javastone.toolkit.comparer.yml.metadata.type.FileType;
import net.javastone.toolkit.core.model.CompareResult;
import net.javastone.toolkit.core.utils.Args;
import net.javastone.toolkit.core.utils.Compare;
import net.javastone.toolkit.core.utils.Jsons;
import net.javastone.toolkit.core.utils.Xmls;
import net.javastone.toolkit.core.utils.Yamls;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by sdliang on 2019/10/10.
 */
public class ComparerApp {

  public static void main(String[] args) throws IOException {
    //源文件
    String from = Args.getParameter(args, 0).orElseThrow(() -> new RuntimeException("请指定源文件"));
    //目标文件
    String to = Args.getParameter(args, 1).orElseThrow(() -> new RuntimeException("请指定目标文件"));
    //输出类型
    FileType fileType = getFileType(args);
    //比对
    CompareResult result = compare(from, to, fileType);
    //输出
    String resultFile = Args.getParameter(args, 3).orElse(null);
    output(result, resultFile);
  }

  /**
   * 文件格式
   *
   * @param args
   * @return
   */
  private static FileType getFileType(String[] args) {
    //类型
    final String allowTypeStr = Stream.of(FileType.values()).map(FileType::name)
        .collect(Collectors.joining("/"));
    String fileTypeStr = Args.getParameter(args, 2)
        .orElseThrow(() -> new RuntimeException("请指定文件格式:" + allowTypeStr));
    FileType fileType = FileType.valueOf(fileTypeStr.toUpperCase());
    if (fileType == null) {
      fileType = FileType.JSON;
    }
    return fileType;
  }

  /**
   * 比对两个文件
   *
   * @param fromFile 源
   * @param toFile   目标
   * @param fileType
   * @return
   */
  private static CompareResult compare(String fromFile, String toFile, FileType fileType)
      throws IOException {
    try (FileInputStream fromIS = new FileInputStream(fromFile);
         FileInputStream toIS = new FileInputStream(toFile)) {
      JsonNode source;
      JsonNode target;
      String fromStr = IOUtils.toString(fromIS, Charset.defaultCharset());
      String toStr = IOUtils.toString(toIS, Charset.defaultCharset());
      switch (fileType) {
        case JSON:
          source = Jsons.tree(fromStr);
          target = Jsons.tree(toStr);
          break;
        case XML:
          source = Xmls.tree(fromStr);
          target = Xmls.tree(toStr);
          break;
        case YML:
          source = Yamls.tree(fromStr);
          target = Yamls.tree(toStr);
          break;
        default:
          source = Jsons.tree(fromStr);
          target = Jsons.tree(toStr);
          break;
      }
      //比对
      return Compare.compareJson(source, target);
    }
  }

  /**
   * 结果输出
   *
   * @param result
   * @param resultFile
   */
  private static void output(CompareResult result, String resultFile) throws IOException {
    //内容
    List<String> results = new ArrayList<>();
    results.add("================源文件特有属性====================");
    results.addAll(result.getFromProps());

    results.add("================目标文件特有属性====================");
    results.addAll(result.getToProps());

    results.add("================源文件和目标文件属性值不一样的结果====================");
    result.getValueDiffs().stream().map(CompareResult.ValueDiff::toString).forEach(results::add);
    //输出流
    if (resultFile != null && !"".equals(resultFile)) {
      try (OutputStream stream = new FileOutputStream(new File(resultFile))) {
        IOUtils.writeLines(results, null, stream, Charset.defaultCharset());
      }
    }
    //控制台输出
    results.forEach(System.out::println);
  }
}
